<template>
    <div class="wrap">
        <input
            type="text"
            v-model="value"
            placeholder="发布的ID，不用带live/"
        />
        <div
            class=""
            @click="startPublish()"
        >
            点击发布
        </div>
        <div
            class=""
            @click="stopPublish()"
        >
            点击停止发布
        </div>
        <div
            class=""
            @click="startPlay()"
        >
            点击播放
        </div>
        <div
            class=""
            @click="stopPlay()"
        >
            点击停止播放
        </div>
        <br />
        <div
            class=""
            @click="getShareScreen()"
        >
            点击获取全部窗口(点击选择一个窗口后点击发布，发布成功再点击播放)
        </div>
        <div
            :class="currentShareScreenId == window.id ? 'window-bg' : ''"
            v-for="window in shareScreenIdArr"
            :key="window.id"
            @click="selectShareScreen(window)"
        >
            {{
                window.id.indexOf('screen') !== -1
                    ? '屏幕------' + window.name + 'ID------' + window.id
                    : '窗口------' + window.name + 'ID------' + window.id
            }}
        </div>
        <div
            class=""
            @click="openWebrtc()"
        >
            点击打开webrtc
        </div>
        <div
            v-if="shareScreenIdArr.length > 0"
            class=""
            @click="clearWindow()"
        >
            不选择任何窗口
        </div>

        <div class="video-wrap">
            <div class="">发布的流</div>
            <video
                id="publishVideo"
                muted
                autoplay
                controls
                playsinline
                class="video-item"
            ></video>
        </div>
        <div class="video-wrap">
            <div class="">播放的流</div>
            <video
                id="playVideo"
                :muted="false"
                autoplay
                controls
                playsinline
                class="video-item"
            ></video>
        </div>
    </div>
</template>

<script>
export default {
    name: 'Home',

    data() {
        return {
            value: 'tch_1',
            publishPC: null,
            playPC: null,
            publishUrl: '',
            baseUrl: 'http://192.168.2.111:8080',
            // baseUrl: "http://giroro.tpddns.cn:8081",
            shareScreenIdArr: [],
            currentShareScreenId: null,
            size: [
                {
                    width: 2195,
                    height: 1195
                },
                {
                    width: 1440,
                    height: 860
                }
            ]
        };
    },

    mounted() {},
    methods: {
        // 获取本地视频流
        getLocalStream() {
            return new Promise(async (resolve, reject) => {
                const mediaStream = await navigator.mediaDevices.getUserMedia({
                    video: true,
                    audio: true
                });
                console.log('mediaStream', mediaStream);
                let dom = document.getElementById('publishVideo');
                if (dom) {
                    dom.srcObject = mediaStream;
                }
                resolve(mediaStream);
            });
        },
        // 开始发布
        async startPublish() {
            let streamId = this.value;
            console.log('开始发布', streamId);
            let mediaStream = null;
            if (this.currentShareScreenId) {
                mediaStream = document.getElementById('publishVideo').srcObject;
            } else {
                mediaStream = await this.getLocalStream();
            }

            this.publishPC = new RTCPeerConnection();

            this.publishPC.oniceconnectionstatechange = () => {
                console.log('oniceconnectionstatechange', this.publishPC.iceConnectionState);
                if (this.publishPC.iceConnectionState == 'disconnected') {
                    console.log('发布结束');
                    document.getElementById('playVideo').srcObject = null;
                    this.stopTrack();
                    // this.$message.error("发布结束");
                }
            };
            this.publishPC.onicecandidate = (e) => {
                console.log('onicecandidate', e.candidate);
            };
            // this.publishPC.addTransceiver("video", {
            // direction: 'sendrecv',
            // sendEncodings: [
            //     { rid: 'r0', maxBitrate: 10000000 ,maxFramerate:60},
            //     { rid: 'r1', maxBitrate: 5000000, scaleResolutionDownBy: 2.0,maxFramerate:60 }
            // ]
            // });
            mediaStream.getTracks().forEach((t) => {
                if (t.kind=="video"){
                    const sender = this.publishPC.addTrack(t, mediaStream);
                    // // 获取编码参数
                    const params = sender.getParameters();
                    if (params.encodings.length > 0) {
                        params.encodings[0].networkPriority = 'high';
                        params.encodings[0].priority = 'high';
                        params.encodings[0].maxBitrate = 40000000;
                        params.encodings[0].maxFramerate = 60;
                        params.encodings[0].active = true;
                        sender.setParameters(params);
                    }
                    console.log('params', params);
                }
                // this.publishPC.addTrack(t, mediaStream);

                if (t.kind == 'audio') {
                    const transceiver = this.publishPC.addTransceiver(t, { direction: 'sendrecv' });
                    const { codecs } = RTCRtpSender.getCapabilities('audio');
                    let pcmaIndex = codecs.findIndex((e) => e.mimeType == 'audio/PCMA');
                    if (pcmaIndex == -1) return;
                    const selectcodecs = codecs[pcmaIndex];
                    codecs.splice(pcmaIndex, 1);
                    codecs.unshift(selectcodecs);
                    console.log('codecs is ', codecs);
                    transceiver.setCodecPreferences(codecs);
                    console.log('选择的codec', selectcodecs);
                }
            });
            const offer = await this.publishPC.createOffer();
            await this.publishPC.setLocalDescription(offer);

            let publishUrl = this.baseUrl + `/webrtc/push/live/${streamId}?name=${streamId}`;
            console.log('publishUrl', publishUrl);
            this.publishUrl = publishUrl;

            const result = await fetch(this.publishUrl, {
                method: 'POST',
                mode: 'cors',
                cache: 'no-cache',
                credentials: 'include',
                redirect: 'follow',
                referrerPolicy: 'no-referrer',
                headers: { 'Content-Type': 'application/sdp' },
                body: offer.sdp
            });
            const remoteSdp = await result.text();
            console.warn('发布结果', result);

            if (result.status == 200 || result.status == 201) {
                console.warn('发布成功');
                // this.$message.success("发布成功");
            } else {
                // this.$message.error("发布失败");
                console.error('发布成功');
                this.stopTrack();
                return;
            }

            // document.getElementById("publish-remoteSdp").innerText = remoteSdp;
            await this.publishPC.setRemoteDescription(
                new RTCSessionDescription({ type: 'answer', sdp: remoteSdp })
            );
        },
        // 结束发布
        async stopPublish() {
            let streamId = this.value;
            const result = await fetch(
                this.baseUrl + `/api/closestream?streamPath=live/${streamId}`,
                {
                    method: 'GET',
                    mode: 'cors',
                    cache: 'no-cache',
                    credentials: 'include',
                    redirect: 'follow',
                    referrerPolicy: 'no-referrer'
                }
            );
            console.log('关闭流结果', result);
            document.getElementById('playVideo').srcObject = null;
            if (result.status == 200 || result.status == 201) {
                this.publishPC?.close();
                this.stopTrack();
            }
        },
        // 播放流
        async startPlay() {
            let streamId = this.value;
            let dom = document.getElementById('playVideo');
            this.playPC = new RTCPeerConnection();
            this.playPC.ontrack = (e) => {
                console.log('ontrack', e);
                if (e.streams.length === 0 || !document.getElementById('playVideo')) return;
                dom.srcObject = e.streams[0];
            };
            this.playPC.oniceconnectionstatechange = (e) => {
                console.log(
                    'oniceconnectionstatechange',
                    e,
                    this.playPC,
                    this.playPC.iceConnectionState
                );
                if (this.playPC.iceConnectionState == 'connected') {
                    console.log('播放成功', streamId);
                    // this.$message.success("播放成功");
                    console.warn('播放成功', streamId);
                }
                if (this.playPC.iceConnectionState == 'disconnected') {
                    console.error('播放结束', streamId);
                    // this.$message.error("播放结束");
                    document.getElementById('playVideo').srcObject = null;
                }
            };
            this.playPC.onconnectionstatechange = (e) => {
                console.log('state changed', e, this.playPC.connectionState);
            };
            this.playPC.onicecandidate = (e) => {
                console.log('onicecandidate', e);
            };
            this.playPC.addTransceiver('video', { direction: 'recvonly' });
            this.playPC.addTransceiver('audio', { direction: 'recvonly' });
            // const dc = this.playPC.createDataChannel('sdp');
            const offer = await this.playPC.createOffer();
            await this.playPC.setLocalDescription(offer);
            const searchParams = new URLSearchParams(location.search);
            const streamPath = searchParams.get('streamPath') || 'live/' + streamId;
            searchParams.delete('streamPath');
            const result = await fetch(this.baseUrl + `/webrtc/play/${streamPath}`, {
                method: 'POST',
                mode: 'cors',
                cache: 'no-cache',
                credentials: 'include',
                redirect: 'follow',
                referrerPolicy: 'no-referrer',
                headers: { 'Content-Type': 'application/sdp' },
                body: offer.sdp
            });
            console.log('播放结果', result);
            if (result.status == 200 || result.status == 201) {
                console.log('播放成功');
            } else {
                console.error('播放失败', result);
                // this.$message.error("播放失败");
                this.stopPlay();
                return;
            }
            const remoteSdp = await result.text();
            // document.getElementById("play-remoteSdp").innerText = remoteSdp;
            await this.playPC.setRemoteDescription(
                new RTCSessionDescription({ type: 'answer', sdp: remoteSdp })
            );
        },
        // 结束播放流
        stopPlay() {
            document.getElementById('playVideo').srcObject = null;
            this.playPC?.close();
        },
        // 停止轨道
        stopTrack() {
            let dom = document.getElementById('publishVideo');
            if (dom && dom.srcObject) {
                var tracks = dom.srcObject.getTracks(); // if only audio was requested, this will be an array with one MediaStreamTrack
                tracks.map((track) => {
                    track.stop();
                });
                document.getElementById('publishVideo').srcObject = null;
            }
        },
        // 切换视频源
        switchSource(equipIdObj) {
            let dom = document.getElementById(this.data.streamId);
            if (dom) {
                dom.srcObject.getTracks().forEach((t) => {
                    // t.stop();
                    dom.srcObject.removeTrack(t);
                });

                navigator.mediaDevices
                    .getUserMedia({
                        video: {
                            deviceId: equipIdObj.video
                        },
                        audio: {
                            deviceId: equipIdObj.microPhone
                        }
                    })
                    .then((stream) => {
                        let senders = this.publishPC.getSenders();

                        senders.map((track) => {
                            if (track.track.kind === 'video') {
                                track.replaceTrack(stream.getVideoTracks()[0]);
                            }
                            if (track.track.kind === 'audio') {
                                track.replaceTrack(stream.getAudioTracks()[0]);
                            }
                        });
                        document.getElementById(this.data.streamId).srcObject = stream;
                        console.log('切换视频源publishPC', this.publishPC, senders, stream);
                    });
            }
        },
        // 获取屏幕的窗口流id
        getShareScreen() {
            window.electronAPI.navigatorShare(['screen', 'window']).then((res) => {
                this.shareScreenIdArr = res;
                console.log('共享屏幕的所有屏幕流', this.shareScreenIdArr);
                this.getCurrentWindow()
            });
        },
        // 选择窗口
        selectShareScreen(screen) {
            this.currentShareScreenId = screen.id;
            // 获取屏幕流
            this.changeScreenStream(screen.id).then((res) => {
                console.log('切换屏幕流成功');
                document.getElementById('publishVideo').srcObject = res;
            });
        },
        clearWindow() {
            this.currentShareScreenId = null;
            document.getElementById('publishVideo').srcObject = null;
        },
        // 获取屏幕流
        changeScreenStream(screenId) {
            return new Promise((resolve, reject) => {
                // let {width,height} = screenId == "screen:0:0" ? this.size[0] : this.size[1];
                console.warn('id:', screenId);
                let videoMediaOption = {
                    audio: {
                        mandatory: {
                            chromeMediaSource: 'desktop'
                        }
                    },
                    // audio: false,
                    video: {
                        mandatory: {
                            chromeMediaSource: 'desktop',
                            chromeMediaSourceId: screenId,
                            // minWidth: width,
                            // minHeight: height,
                            minWidth: 1920,
                            minHeight: 1080,
                            // maxWidth:1920,
                            // maxHeight:1080,
                            minFrameRate: 30,
                            maxFrameRate: 60
                            // maxFrameRate:60,
                            // frameRate: { ideal: 60, max: 120 },
                            // bitrate: 2000000 // 2 Mbps
                        }
                    }
                };
                navigator.mediaDevices
                    .getUserMedia(videoMediaOption)
                    .then((mediaStream) => {
                        mediaStream.getTracks().forEach((track) => {
                            track.contentHint = 'detail';
                        });
                        resolve(mediaStream);
                    })
                    .catch((err) => {
                        reject(err);
                    });
            });
        },
        openWebrtc() {
            window.electronAPI.openWebrtc();
        },
        // 获取当前屏幕窗口
        async getCurrentWindow(){
            let currentWindowId = await window.electronAPI.navigatorCurrentWindowShare();
            console.log("当前屏幕窗口ID",currentWindowId);
            this.shareScreenIdArr.push({
                name: "当前窗口",
                id: currentWindowId
            })
        }
    },
    beforeUnmount() {
        this.stopTrack();
        this.publishPC?.close();
        this.playPC?.close();
    }
};
</script>

<style scoped>
.video-wrap {
    display: inline-block;
    border: 1px solid #ccc;
}
.video-item {
    width: 300px;
    height: 200px;
    object-fit: cover;
}
.window-bg {
    background: red;
}
</style>

